/**
 * 文件系统操作工具类
 */


var fs = require("fs");


/**
 * 异步读取文件
 * <p>分步骤open、read, Buffer接受文件内容</p>
 * @param filePath
 */
function fsRead(filePath) {
    // 打开文件
    fs.open(filePath, 'r', function(err, fd) {
        if (err) {
            console.log("异步读取文件["+filePath+"]fsReadFile_original.open: " + err)
            throw err;
        }
        var buffer = Buffer.alloc(255);
        // 读取文件
        fs.read(fd, buffer, 0, 50, null, function(err, bytesRead, buffer) {
            if (err) {
                console.log("异步读取文件["+filePath+"]fsReadFile_original.read err: " + err)
                throw err;
            }
            // 打印出buffer中存入的数据
            console.log("异步读取文件["+filePath+"]fsReadFile_original.read: ", buffer.slice(0, bytesRead).toString());

            // 关闭文件
            // fs.close(fd);
        });
    });
}

/**
 * 异步读取文件
 * @param filePath
 */
function fsReadFile(filePath) {
    fs.readFile(filePath, {flag:"r",encoding:"utf-8"}, function (err, data) {
        if(err) {
            console.log("异步读取文件["+filePath+"]fsReadFile.readFile: " + err)
        } else {
            console.log("异步读取文件["+filePath+"]fsReadFile.readFile: " + data);
        }
    })
}

/**
 * 同步读取文件
 * <p>分步骤open、read, Buffer接受文件内容</p>
 * @param filePath
 * @returns {*}
 */
function fsReadSync(filePath) {
    let fd;
    try {
        // 同步读取
        fd = fs.openSync(filePath, "r");
        let buf = Buffer.alloc(255);
        let file = fs.readSync(fd, buf, 0, 50, null);
        // console.log("fsReadFileSync_original(): " + file);
        // console.log(buf.toString())
        return buf.toString();
    } catch (e) {
        console.log("同步读取文件fsReadFileSync_original: ", e);
        return e;
    } finally {
        if (fd !== undefined)
            fs.closeSync(fd);
    }
}

/**
 * 同步读取文件
 * @param filePath
 * @returns {*}
 */
function fsReadFileSync(filePath) {
    try {
        // 同步读取
        let file = fs.readFileSync(filePath, {flag:"r",encoding:"utf-8"})
        // console.log("fsReadFileSync(): " + file);
        return file;
    } catch (e) {
        console.log("同步读取文件fsReadFileSync(): ", e);
        return e;
    }
}

/**
 * 异步读取文件
 * <p>Promise对象用来将异步操作以同步操作的流程表达出来</p>
 * @param filePath 文件路径
 * @returns {Promise<unknown>}
 */
function fsReadFilePromise(filePath) {
    //Promise对象用来将异步操作以同步操作的流程表达出来
	return new Promise(function (resolve, reject) {
        // 异步读取
        fs.readFile(filePath, {flag:"r",encoding:"utf-8"}, function (err, data) {
            if(err) {
                // console.log("fs.readFile(): " + err)
                reject(err);
            } else {
                // console.log("fs.readFile(): " + data);
                resolve(data);
            }
        })
    })
}

/**
 * 异步读取目录
 * @param dir
 * @returns {*}
 */
function fsReaddir(dir) {
    fs.readdir(dir, function (err, files) {
        if(err) {
            console.log("异步读取目录["+dir+"]:" + err);
            return;
        }
        // files.forEach(function (file) {
        //     console.log("异步读取目录["+dir+"]:" + file);
        // })
        console.log("异步读取目录["+dir+"]:" + files);
    });
}

/**
 * 同步读取目录
 * @param dir
 * @returns {*}
 */
function fsReaddirSync(dir) {
    let dirItem = fs.readdirSync(dir);
    return dirItem;
}

/**
 * 异步创建目录
 * @param dir
 * @returns {*}
 */
function fsMkdir(dir) {
    return new Promise(function(resolve, reject) {
        fs.mkdir(dir, { recursive: true }, function(err) {
            if(err) {
                reject(err)
            } else {
                resolve()
            }
        })
    })
}

/**
 * 同步写入文件
 * @param filePath
 * @param type w: 覆盖文件内容; a: 追加文件内容
 * @param content
 */
function fsWriteSync(filePath, type, content) {
    type = type ? type : "a";
    let txt = type === "w" ? "写成" : "追加"
    var fd;
    try {
        if(!content) {
            "["+new Date().toLocaleDateString()+"]文件内容被"+txt+"这句话了"
        }
        fd = fs.openSync(filePath, type);
        fs.writeSync(fd, content);
        // console.log("writeSync() 文件内容被"+txt+"这句话了");
    } catch (err) {
        //console.log(arguments);
        console.log("writeSync() 文件内容被"+txt+"这句话了" + err);
    } finally {
        if (fd !== undefined)
            fs.closeSync(fd);
        console.log("writeSync() 文件写入内容，并关闭文件流。。。");
    }
}

/**
 * 同步覆盖写入文件
 * @param filePath
 * @param content
 */
function fsWriteFileSync(filePath, content) {
    try {
        if(!content) {
            "["+new Date().toLocaleDateString()+"]写入的数据"
        }
        fs.writeFileSync(filePath, content);
        // console.log("appendFileSync() 数据已被写入到文件");
    } catch (err) {
        console.log("appendFileSync() 数据已被写入到文件" + err);
    } finally {
        console.log("appendFileSync() 文件写入内容，并关闭文件流。。。");
    }
}

/**
 * 同步追加写入文件
 * @param filePath
 * @param content
 */
function fsAppendFileSync(filePath, content) {
    try {
        if(!content) {
            "\n["+new Date().toLocaleDateString()+"]追加的数据"
        }
        fs.appendFileSync(filePath, content);
        // console.log("appendFileSync() 数据已被追加到文件");
    } catch (err) {
        console.log("appendFileSync() 数据已被追加到文件" + err);
    } finally {
        // console.log("appendFileSync() 文件写入内容，并关闭文件流。。。");
    }
}

/**
 * 读取文件流
 * @param filePath
 */
function fsReadStream(filePath) {
    // let rs = fs.createReadStream(filePath, {flags: "r", encoding: "utf-8"});
    let rs = fs.createReadStream(filePath, {flags: "r"});
    console.log(rs)

    rs.on("data", function (re) {
        console.log("读取到文件内容：" + re.length)
        console.log(re)
    })

    rs.on("open", function (re) {
        console.log("文件流读取已打开，返回：" + re)
    })

    rs.on("close", function () {
        console.log("文件流读取已关闭")
    });
}

/**
 * 写入文件流
 * @param filePath
 * @param newFilePath
 */
function fsWriteStream(filePath, newFilePath) {
    // let rs = fs.createReadStream(filePath, {flags: "r", encoding: "utf-8"});
    let rs = fs.createReadStream(filePath, {flags: "r"});
    console.log(rs)

    let ws = fs.createWriteStream(newFilePath, {flags: "w"});

    rs.on("data", function (re) {
        console.log("读取到文件内容：" + re.length)
        // console.log(re)
        ws.write(re, () => {console.log("流文件写入完成")});
    })

    rs.on("open", function (re) {
        console.log("文件流读取已打开，返回：" + re)
    })

    rs.on("close", function () {
        ws.end();
        console.log("文件流读取已关闭")
    });
}

/**
 * 使用通道pipe写入文件流
 * @param filePath
 * @param newFilePath
 */
function fsWriteStreamPipe(filePath, newFilePath) {
    // let rs = fs.createReadStream(filePath, {flags: "r", encoding: "utf-8"});
    let rs = fs.createReadStream(filePath, {flags: "r"});
    console.log(rs)

    let ws = fs.createWriteStream(newFilePath, {flags: "w"});

    // 管道连通
    rs.pipe(ws);

    rs.on("open", function (re) {
        console.log("文件流读取已打开，返回：" + re)
    })

    rs.on("close", function () {
        console.log("文件流读取已关闭")
    });
}

/**
 * 同步读取csv文件
 * @param filePath
 */
function fsReadCsvFileDatasSync(filePath) {
    String.prototype.myReplace = function(f,e){//吧f替换成e
        var reg=new RegExp(f,"g"); //创建正则RegExp对象
        return this.replace(reg,e);
    }
    let data = fs.readFileSync(filePath, {flag:"r", encoding:"utf-8"});
    let datas = new Array();
    // console.log(data.toString())
    let rows = data.toString().split("\r\n");
    for (let i = 1; i < rows.length-1; i++) {
        datas.push(rows[i].split(",")[0].myReplace("\"", "") + "," + rows[i].split(",")[1].myReplace("\"", ""));
    }
    // console.log(datas)
    return datas;
}

/***
 * 输出模块函数
 */
// 文本文件读取
exports.fsRead = fsRead;
exports.fsReadSync = fsReadSync;
exports.fsReadFile = fsReadFile;
exports.fsReadFileSync = fsReadFileSync;
exports.fsReadFilePromise = fsReadFilePromise;
// 文件目录读取
exports.fsReaddir = fsReaddir;
exports.fsReaddirSync = fsReaddirSync;
// 文件目录创建
exports.fsMkdir = fsMkdir;
// 文本文件写入
exports.fsWriteSync = fsWriteSync;
exports.fsWriteFileSync = fsWriteFileSync;
exports.fsAppendFileSync = fsAppendFileSync;
// 读取流数据
exports.fsReadStream = fsReadStream;
exports.fsWriteStream = fsWriteStream;
exports.fsWriteStreamPipe = fsWriteStreamPipe;
// 同步读取csv文件
exports.fsReadCsvFileDatasSync = fsReadCsvFileDatasSync;
